#include <iostream>
#include "../aed2/aed2.h"
#include "../src/tablero.h"


using namespace std;

void test_crear(ostream&){
	Tablero<String> t;
	ASEGURAR(t.Casillas().Cardinal(), 1);
	ASEGURAR(t.Continentes().Cardinal(), 1);
	
	ASEGURAR(t.Casillas().CrearIt().Siguiente(), 0);
	ASEGURAR(t.Continentes().CrearIt().Siguiente(), 0);
	
	ASEGURAR(t.CasillasDe(0).Cardinal(), 1);
	ASEGURAR(t.CasillasDe(0).CrearIt().Siguiente(), 0);
}

void test_agregadoCasillasConexiones(ostream&){
	//Crea el tablero con un continente y una casilla
	Tablero<String> t;

	//Se agrega una nueva casilla en el mismo continente que la casilla 0, conectada de ida y vuelta con 0
	String s1("m_1-0");
	String s2("m_0-1");
	t.Contener(0, s1, s2);
	
	Conj<Casilla> cc;
	cc.Agregar(0);
	cc.Agregar(1);

	Conj<Continente> casContinente0(cc);
	
	Conj<Continente> continentes;
	continentes.Agregar(0);
	
	ASEGURAR(t.Casillas(), cc);
	ASEGURAR(t.Continentes(), continentes);

	ASEGURAR(t.CasillasDe(0), casContinente0);
	AFIRMAR(t.ContinenteDe(0) == 0);
	AFIRMAR(t.ContinenteDe(1) == 0);
	
	AFIRMAR(t.Conectadas(0, 1));
	
	
	//Se agrega una nueva casilla en un continente nuevo, conectada de ida y vuelta con 1
	String s3("m_2-1");
	String s4("m_1-2");
	t.Agregar(1, s3, s4	);

	cc.Agregar(2);
	continentes.Agregar(1);
	Conj<Casilla> casContinente1;
	casContinente1.Agregar(2);
	
	ASEGURAR(t.Casillas(), cc);
	ASEGURAR(t.Continentes(), continentes);
	AFIRMAR(t.ContinenteDe(0) == 0);
	AFIRMAR(t.ContinenteDe(1) == 0);
	AFIRMAR(t.ContinenteDe(2) == 1);

	ASEGURAR(t.CasillasDe(0), casContinente0);
	ASEGURAR(t.CasillasDe(1), casContinente1);

	AFIRMAR(t.Conectadas(0, 1));
	AFIRMAR(t.Conectadas(1, 2));
	NEGAR(t.Conectadas(0, 2));
	
	//Se agrega una nueva conexión de 2 a 1 
	String s5("m2_2-1");
	t.Movilizar(2, 1, s5);

	ASEGURAR(t.Casillas(), cc);
	ASEGURAR(t.Continentes(), continentes);
	
	AFIRMAR(t.Conectadas(0, 1));
	AFIRMAR(t.Conectadas(1, 2));
	NEGAR(t.Conectadas(0, 2));
	
	//Se agrega una conexión de ida y vuelta entre 0 y 2
	String s6("m_0-2");
	String s7("m_2-0");
	t.Conectar(0, 2, s6, s7);

	ASEGURAR(t.Casillas(), cc);
	ASEGURAR(t.Continentes(), continentes);

	AFIRMAR(t.Conectadas(1, 0));
	AFIRMAR(t.Conectadas(2, 1));
	AFIRMAR(t.Conectadas(2, 0));
	
	//Se agrega una nueva casilla en el mismo continente que la casilla 2, conectada de ida y vuelta con 2
	String s8("m_3-2");
	String s9("m_2-3");
	t.Contener(2, s8, s9);
	
	cc.Agregar(3);
	casContinente1.Agregar(3);

	ASEGURAR(t.Casillas(), cc);

	AFIRMAR(t.ContinenteDe(0) == 0);
	AFIRMAR(t.ContinenteDe(1) == 0);
	AFIRMAR(t.ContinenteDe(2) == 1);
	AFIRMAR(t.ContinenteDe(3) == 1);
	
	ASEGURAR(t.Continentes(), continentes);	
	ASEGURAR(t.CasillasDe(0), casContinente0);
	ASEGURAR(t.CasillasDe(1), casContinente1);

	AFIRMAR(t.Conectadas(0, 1));
	AFIRMAR(t.Conectadas(1, 2));
	AFIRMAR(t.Conectadas(0, 2));
	AFIRMAR(t.Conectadas(3, 2));
	NEGAR(t.Conectadas(0, 3));
	NEGAR(t.Conectadas(1, 3));
	
	//Se agrega una nueva casilla en un continente nuevo, conectada de ida y vuelta con 3
	String s10("m_4-3");
	String s11("m_3-4");
	t.Agregar(3, s10, s11);
	
		
	cc.Agregar(4);
	Conj<Casilla> casContinente2;
	casContinente2.Agregar(4);
	continentes.Agregar(2);

	ASEGURAR(t.Casillas(), cc);
	ASEGURAR(t.Continentes(), continentes);	

	AFIRMAR(t.ContinenteDe(0) == 0);
	AFIRMAR(t.ContinenteDe(1) == 0);
	AFIRMAR(t.ContinenteDe(2) == 1);
	AFIRMAR(t.ContinenteDe(3) == 1);
	AFIRMAR(t.ContinenteDe(4) == 2);
	
	ASEGURAR(t.CasillasDe(0), casContinente0);
	ASEGURAR(t.CasillasDe(1), casContinente1);
	ASEGURAR(t.CasillasDe(2), casContinente2);

	AFIRMAR(t.Conectadas(1, 0));
	AFIRMAR(t.Conectadas(2, 1));
	AFIRMAR(t.Conectadas(2, 0));
	AFIRMAR(t.Conectadas(2, 3));
	AFIRMAR(t.Conectadas(3, 4));
	NEGAR(t.Conectadas(2, 4));
	NEGAR(t.Conectadas(0, 3));
	NEGAR(t.Conectadas(0, 4));
	NEGAR(t.Conectadas(1, 3));
	NEGAR(t.Conectadas(1, 4));
}


void test_origenesSalidasDestinos(ostream&){
	//Crea el tablero con un continente y una casilla
	Tablero<String> t;

	ASEGURAR(t.Salidas(0).Cardinal(),0);
	
	//Se agrega una nueva casilla en un nuevo continente, conectada de ida y vuelta con 0
	String s0("m->0");
	String s1("m->1");
	t.Agregar(0, s0, s1);
	
	AFIRMAR(t.Salidas(0).Cardinal() == 1);
	AFIRMAR(t.Destinos(0).Siguiente().casilla == 1);
	ASEGURAR(t.Destinos(0).Siguiente().movimiento, "m->1");
	
	Conj<Casilla> origenes1s1;
	origenes1s1.Agregar(0);
	
	AFIRMAR(t.Salidas(1).Cardinal() == 1);
	AFIRMAR(t.Origenes(1, s1).Cardinal() == 1);
	ASEGURAR(t.Origenes(1, s1), origenes1s1);
	
	AFIRMAR(t.Destinos(1).Siguiente().casilla == 0);
	ASEGURAR(t.Destinos(1).Siguiente().movimiento, "m->0");
	
	//Se agrega una nueva casilla en el mismo continente que la casilla 1, conectada de ida y vuelta con ella
	String s2("m->2");
	t.Contener(1, s1, s2);
	
	origenes1s1.Agregar(2);

	AFIRMAR(t.Salidas(1).Cardinal() == 2);
	Tablero<String>::ItDestinos itDestinos = t.Destinos(1);

	NEGAR(itDestinos.HayAnterior());
	AFIRMAR(itDestinos.HaySiguiente());
	itDestinos.Avanzar();
	AFIRMAR(itDestinos.HaySiguiente());
	itDestinos.Retroceder();
	AFIRMAR(itDestinos.HaySiguiente());
	itDestinos.Avanzar();
	AFIRMAR(itDestinos.HaySiguiente());
	itDestinos.Avanzar();
	NEGAR(itDestinos.HaySiguiente());
	
	AFIRMAR(t.Origenes(1, s1).Cardinal() == 2);
	AFIRMAR(t.Origenes(1, s1) == origenes1s1);
	
	
	AFIRMAR(t.Salidas(2).Cardinal() == 1);
	AFIRMAR(t.Destinos(2).Siguiente().casilla == 1);
	ASEGURAR(t.Destinos(2).Siguiente().movimiento, s1);	
	
	//Se agrega una nueva conexión de 2 a 1
	String s4("m->1_2");
	t.Movilizar(2, 1, s4);

	AFIRMAR(t.Salidas(1).Cardinal() == 2);
	AFIRMAR(t.Salidas(2).Cardinal() == 2);
	
	//Se agrega una conexión de ida y vuelta entre 0 y 2
	t.Conectar(0, 2, s2, s0);
	AFIRMAR(t.Salidas(0).Cardinal() == 2);
	itDestinos = t.Destinos(0);
	AFIRMAR(itDestinos.HaySiguiente());
	itDestinos.Avanzar();
	AFIRMAR(itDestinos.HaySiguiente());
	itDestinos.Retroceder();
	AFIRMAR(itDestinos.HaySiguiente());
	itDestinos.Avanzar();
	AFIRMAR(itDestinos.HaySiguiente());
	itDestinos.Avanzar();
	NEGAR(itDestinos.HaySiguiente());
	
	Conj<Casilla> origenes0s0;
	origenes0s0.Agregar(1);
	origenes0s0.Agregar(2);
	
	AFIRMAR(t.Origenes(0, s0).Cardinal() == 2);
	AFIRMAR(t.Origenes(0, s0) == origenes0s0);
	String sarasa("Sarasa");
	
	Conj<Casilla> origenesSarasa;
	origenesSarasa.Agregar(0);
	
	ASEGURAR(t.OrigenesR(0, sarasa), origenesSarasa);
	
	
	//Se agrega una nueva casilla en un nuevo continente, conectada de ida y vuelta con 2
	String s3("m->3");
	t.Agregar(2, s2, s3);

	AFIRMAR(t.Salidas(2).Cardinal() == 4);
	itDestinos = t.Destinos(2);

	NEGAR(itDestinos.HayAnterior());
	AFIRMAR(itDestinos.HaySiguiente());
	itDestinos.Avanzar();
	AFIRMAR(itDestinos.HaySiguiente());
	itDestinos.Retroceder();
	AFIRMAR(itDestinos.HaySiguiente());
	itDestinos.Avanzar();
	AFIRMAR(itDestinos.HaySiguiente());
	itDestinos.Avanzar();
	AFIRMAR(itDestinos.HaySiguiente());
	itDestinos.Avanzar();	
	AFIRMAR(itDestinos.HaySiguiente());
	itDestinos.Avanzar();
	NEGAR(itDestinos.HaySiguiente());
	
	Conj<Casilla> origenes2s2;
	origenes2s2.Agregar(0);
	origenes2s2.Agregar(1);
	origenes2s2.Agregar(3);
	
	AFIRMAR(t.Origenes(2, s2).Cardinal() == 3);
	AFIRMAR(t.Origenes(3, s3).Cardinal() == 1);
	
	ASEGURAR(t.Salidas(1).Cardinal(), 2);
	AFIRMAR(t.Destinos(3).Siguiente().casilla == 2);
	ASEGURAR(t.Destinos(3).Siguiente().movimiento, "m->2");		
}


int main(void) {
	Tester& tester = *Tester::Instance();
	
	tester.NuevoSet("Tablero");
	tester.UsarSet("Tablero");
	tester.Declarar("Creacion", &test_crear);
	tester.Declarar("Agregar Casillas y Conexiones", &test_agregadoCasillasConexiones);
	tester.Declarar("Origenes Salidas Destinos", &test_origenesSalidasDestinos);
	
	tester.setVerborragia(3);

	tester.Ejecutar("Tablero");

	return 0;
}

